import { isPortOccupied } from './utils';
import logger from './logger';

export const resolve = require.resolve;

interface TryPortStartOptions {
  callback: (err: Error, port: number, host: string) => void;
  host?: string;
  port?: number;
  retryWhilePortInUsed?: boolean;
  getNextPort?: (port: number) => number;
}

export function tryPortStart(options: TryPortStartOptions) {
  let timer: any;
  const defaults = {
    host: '0.0.0.0',
    port: '8000',
    tryDelay: 2000,
    retryWhilePortInUsed: true,
    getNextPort: (port: number) => port + 1,
  };
  const { host, port, callback, tryDelay, getNextPort, retryWhilePortInUsed } = Object.assign({}, defaults, options);

  function safeStart(host: string, port: number, callback: (err: Error | null, port: number, host: string) => void) {
    clearTimeout(timer);
    isPortOccupied(host, port, (err, flag) => {
      if (err) {
        callback && callback(err, port, host);
        return;
      }
      if (!flag) {
        callback && callback(null, port, host);
        return;
      }
      if (!retryWhilePortInUsed) {
        logger.error(`Start server failed, port ${port} is in using !`);
        process.exit(-1);
      }
      logger.info(`port [${port}] is in using, try to run at port ${port + 1}....`);
      timer = setTimeout(() => {
        safeStart(host, getNextPort(port), callback);
      }, tryDelay);
    });
  }

  return safeStart(host, port, callback);
}
